
flsys = LibStub("AceAddon-3.0"):NewAddon("flsys", "AceConsole-3.0", "AceEvent-3.0", "AceComm-3.0")
flsys:SetDefaultModuleState(false)

--VARIABLES
local db, raidstocount, newplayerst, min_gp, ep_amt, ep_recur, standard_ilvl, alts_data, numraidmembers
local fra = CreateFrame("Frame", "flsys_TimerFrame")
local rowbuttons = {} --main frame
local maindisplay = 1
local rosterpage = 0

local EQUIPSLOT_MULTIPLIER_1 = { --these 3 tables are modified from LibGearPoints-1.2 (EPGP)
	INVTYPE_HEAD = 1,
	INVTYPE_NECK = 0.5,
	INVTYPE_SHOULDER = 0.75,
	INVTYPE_CHEST = 1,
	INVTYPE_ROBE = 1,
	INVTYPE_WAIST = 0.75,
	INVTYPE_LEGS = 1,
	INVTYPE_FEET = 0.75,
	INVTYPE_WRIST = 0.5,
	INVTYPE_HAND = 0.75,
	INVTYPE_FINGER = 0.5,
	INVTYPE_TRINKET = 1,
	INVTYPE_CLOAK = 0.5,
	INVTYPE_WEAPON = 1.5,
	INVTYPE_SHIELD = 1.5,
	INVTYPE_2HWEAPON = 2,
	INVTYPE_WEAPONMAINHAND = 1,
	INVTYPE_WEAPONOFFHAND = 1,
	INVTYPE_HOLDABLE = 0.5,
	INVTYPE_RANGED = 1.5,
	INVTYPE_RANGEDRIGHT = 1.5,
	INVTYPE_THROWN = 0.5,
	INVTYPE_RELIC = 0.5,
}
local EQUIPSLOT_MULTIPLIER_2 = {
	INVTYPE_WEAPON = 0.5,
	INVTYPE_2HWEAPON = 1,
	INVTYPE_SHIELD = 0.5,
	INVTYPE_RANGED = 0.5,
	INVTYPE_RANGEDRIGHT = 0.5,
}
local CUSTOM_ITEM_DATA = {
	-- T12
	[71674] = { 378, "INVTYPE_SHOULDER" },
	[71688] = { 378, "INVTYPE_SHOULDER" },
	[71681] = { 378, "INVTYPE_SHOULDER" },
	[71668] = { 378, "INVTYPE_HEAD" },
	[71682] = { 378, "INVTYPE_HEAD" },
	[71675] = { 378, "INVTYPE_HEAD" },
	-- T12 Heroic
	[71679] = { 391, "INVTYPE_CHEST" },
	[71686] = { 391, "INVTYPE_CHEST" },
	[71672] = { 391, "INVTYPE_CHEST" },
	[71677] = { 391, "INVTYPE_HEAD" },
	[71684] = { 391, "INVTYPE_HEAD" },
	[71670] = { 391, "INVTYPE_HEAD" },
	[71676] = { 391, "INVTYPE_HAND" },
	[71683] = { 391, "INVTYPE_HAND" },
	[71669] = { 391, "INVTYPE_HAND" },
	[71678] = { 391, "INVTYPE_LEGS" },
	[71685] = { 391, "INVTYPE_LEGS" },
	[71671] = { 391, "INVTYPE_LEGS" },
	[71680] = { 391, "INVTYPE_SHOULDER" },
	[71687] = { 391, "INVTYPE_SHOULDER" },
	[71673] = { 391, "INVTYPE_SHOULDER" },
	--T12 misc
	[71617] = { 391, "INVTYPE_TRINKET" }, -- crystallized firestone
	--T13 normal & heroic (no lfr since n/a)
	[78184] =  { 397, "INVTYPE_CHEST" },
	[78847] =  { 410, "INVTYPE_CHEST" },
	[78848] =  { 410, "INVTYPE_CHEST" },
	[78179] =  { 397, "INVTYPE_CHEST" },
	[78849] =  { 410, "INVTYPE_CHEST" },
	[78174] =  { 397, "INVTYPE_CHEST" },
	[78850] = { 410, "INVTYPE_HEAD" },
	[78182] = { 397, "INVTYPE_HEAD" },
	[78851] = { 410, "INVTYPE_HEAD" },
	[78177] = { 397, "INVTYPE_HEAD" },
	[78172] = { 397, "INVTYPE_HEAD" },
	[78852] = { 410, "INVTYPE_HEAD" },
	[78853] = { 410, "INVTYPE_HAND" },
	[78183] = { 397, "INVTYPE_HAND" },
	[78178] = { 397, "INVTYPE_HAND" },
	[78854] = { 410, "INVTYPE_HAND" },
	[78855] = { 410, "INVTYPE_HAND" },
	[78173] = { 397, "INVTYPE_HAND" },
	[78856] = { 410, "INVTYPE_LEGS" },
	[78181] = { 397, "INVTYPE_LEGS" },
	[78857] = { 410, "INVTYPE_LEGS" },
	[78176] = { 397, "INVTYPE_LEGS" },
	[78171] = { 397, "INVTYPE_LEGS" },
	[78858] = { 410, "INVTYPE_LEGS" },
	[78180] = { 397, "INVTYPE_SHOULDER" },
	[78859] = { 410, "INVTYPE_SHOULDER" },
	[78860] = { 410, "INVTYPE_SHOULDER" },
	[78175] = { 397, "INVTYPE_SHOULDER" },
	[78170] = { 397, "INVTYPE_SHOULDER" },
	[78861] = { 410, "INVTYPE_SHOULDER" },
}
	
--OPTIONS & DB DEFAULTS
local defaults = {
	profile={
		raidstocount = 15,
		newplayerst = 7, --could get rid of this & just calc when setting pos
		min_gp = 500,
		ep_amt = 250,
		ep_recur = 30,
		standard_ilvl = 397,
		players = {},
		alts_data = {},
		dates = {},
		sortlist = {},
		next_award=0,
		lastbroadcast = 0,
		epgplog = {},
		epgp_export = 0, --timestamp
		standings_export = 0, --timestamp
		costlog = {},
		costtotal = 0,
		costrec = 0,
		costs = {
			cauldron = 0,
			feast = 0,
			bcauldron = 0,
		},
		inprogress = false,
		whispopts = true,
		debuglevel = 3,
		promptrecur = true,
		mode=1,
		autoexpense=true,
	},
}

function flsys:GetAlts()
	local altstr = ""
	for alt, main in pairs(db.alts_data) do
		altstr = altstr..(string.format("%s (alt) = %s (main)|n", alt, main))
	end
	return altstr
end

--INITIALIZE/ENABLE
function flsys:OnInitialize()
	flsys.db = LibStub("AceDB-3.0"):New("FlamingLootSysDB", defaults)
	flsys.log = LibStub("AceDB-3.0"):New("flsysdebuglog")
	db = flsys.db.profile
end

function flsys:OnEnable()
	self:RegisterComm("flamingsysdata")
	self:RegisterChatCommand("fss", function() FLMain:Show() end)
	self:RegisterChatCommand("fs", "ProcessChatCmd")
	self:RegisterEvent("CHAT_MSG_ADDON")
	RegisterAddonMessagePrefix("flamingsys")
	flsys:GetConstants()
	flsys:InitializeFrames()
	if db.inprogress then
		if IsInRaid() then
			StaticPopup_Show("RESUME_RAID")
		else
			flsys:EndRaid()
		end
	end
	self:Print("Flaming loot masterlooter addon loaded.  Type /fs for a list of commands.")
	flsys:TrimDebug()
end

function flsys:GetConstants()
	raidstocount = db.raidstocount
	newplayerst = db.newplayerst
	min_gp = db.min_gp
	ep_amt = db.ep_amt
	ep_recur = db.ep_recur
	standard_ilvl = db.standard_ilvl
	alts_data = db.alts_data
end

function flsys:InitializeFrames() --CALLS: MainButtons
	flsys:CheckRows()
	FLMain:SetScale(.8)
	FLMainPrev:GetNormalTexture():SetRotation(-math.pi/2)
	FLMainNext:GetNormalTexture():SetRotation(math.pi/2)
	local count = 0
	local texts = {" ", "EP", "GP", "PR"}
	local widths = {77,42,42,42}
	heading= CreateFrame("Button", "Heading" , FLMain)
	heading:SetSize(200,14)
	for i,w in ipairs(widths) do
		local c = FLMain:CreateFontString(nil, "ARTWORK", "GameFontNormal")
		c:SetParent(Heading)
		c:SetWidth(w)
		c:SetJustifyH("LEFT")
		c:SetPoint("TOPLEFT", FLMain, "TOPLEFT", 15+count, -42)
		c:SetText(texts[i])
		count = count+w
	end	
	
	FLSysAward:SetScript("OnShow", function() FLLog:Hide() end)
	PanelTemplates_SetNumTabs(FLSysAward, 3)
	PanelTemplates_SetTab(FLSysAward, 1)
	PanelTemplates_TabResize(FLSysAwardTab1, 3, 100)
	PanelTemplates_TabResize(FLSysAwardTab2, 3, 100)
	FLSysAwardTab1:SetScale(.9)
	FLSysAwardTab2:SetScale(.9)
	
	FLLogBox.ScrollBar:SetPoint("TOPRIGHT", FLLogContainer, "TOPRIGHT", -4, -17)
	FLLog:SetScript("OnShow", function() FLSysAward:Hide() end)
	FLLogSizer:GetNormalTexture():SetRotation(math.pi)
	
	FLExport.TitleText:SetText("Copy and paste text to spreadsheet")
	FLExport.TitleText:SetJustifyH("LEFT")
	
	FLImportData.TitleText:SetText("Import data")
	FLAddPlayer.TitleText:SetText("Add player")
	FLAddPlayer:SetScale(0.8)
	FLAddPlayerEP:SetNumeric(enable)
	FLAddPlayerGP:SetNumeric(enable)
	FLAddPlayerEP:SetNumber(0)
	FLAddPlayerGP:SetNumber(0)
	
	FLImportData:SetScale(.8)
	
	fra:SetScript("OnUpdate", function(self, elapsed) flsys:CheckTime(self, elapsed) end)
	fra:Hide()
	
	flsys:MainButtons()
	
	FLRosterFrame:SetScale(.8)
	FLRosterFrame.TitleText:SetText("Remove player")
	CreateFrame("Button", "FLRosterDropDown", FLRosterFrame, "UIDropDownMenuTemplate")
	FLRosterDropDown:SetPoint("LEFT")
	
	local function OnClick(self)
	   UIDropDownMenu_SetSelectedName(FLRosterDropDown, self:GetText())
	end
 
	local function initialize(self, level)
	   local info = {}
	   for k,v in pairs(db.sortlist) do
		  info.text = v
		  info.func = OnClick
		  UIDropDownMenu_AddButton(info, level)
	   end
	end
 
	UIDropDownMenu_Initialize(FLRosterDropDown, initialize)
end

function flsys:ProcessChatCmd(input)
	if not input or input:trim() == "" then
		self:Print("Addon commands:\n|cffffff78/fss|r = View the main panel.  Click the picture to toggle between standings and expenses.\n|cffffff78/fs opt|r = View the options window. Also contains a help panel.\n|cffffff78/fs gp [ilvl]|r = View a printout of GP values for an ilvl.\n|cffffff78/fs feast/cauldron/bcauldron|r = Log a feast or cauldron that you provided.  The mats cost of each is set in the options.\n|cffffff78/fs decay|r = Decay ep and gp (default setting will prompt after raids so you don't need to use this).\n|cffffff78/loot|r = (during a raid only) View a cache of the most recent mob's drops and all the rolls made on them.  Only available after the rolling period ends and only for the most recent mob.")
	elseif input=="opt" then
		if not flopt:IsEnabled() then
			fld:Enable()
			flopt:Enable()
		end
		InterfaceOptionsFrame_OpenToCategory("flaming loot ml")
	elseif input=="feast" or input=="cauldron" or input=="bcauldron" then
		flsys:Expense(input)
	elseif input=="decay" then
		if not db.inprogress then
			StaticPopup_Show("DECAY")
		else
			StaticPopup_Show("NOTDURINGRAID")
		end
	else	
		local ilvl = tonumber(string.match(input, "gp (%d+)"))
		if ilvl and ilvl>346 and ilvl<450 then
			flsys:PrintGPValues(ilvl)
		else
			self:Print("Not a valid command. Type /fs to view a list of commands")
		end
	end
end

function flsys:PrintGPValues(ilvl)
	local mult = flsys:Round((2^((ilvl-standard_ilvl)/26)), 3)
	self:Print(ilvl.." values:\n2H weapons: "..(2000*mult).."\nHunter ranged, caster/healer main hand, tank shield: "..(1500*mult).."\nDual wield weapon, hunter 2H, chest, helm, legs, trinket "..(1000*mult).."\nShoulder, belt, boots, gloves: "..(750*mult).."\nOff hand, tank mainhand, thrown, hunter 1H, neck, ring, cloak, bracers\n"..(500*mult))
end

function flsys:debug(lvl, logtype, ...)
	if lvl<=db.debuglevel then
		table.insert(flsys.log.profile, date("%m/%d %H:%M:%S").."---"..logtype.."---"..(table.concat({...}, " ")))
	end
end

function flsys:TrimDebug()
	for i = 1001, #flsys.log.profile do
		table.remove(flsys.log.profile, 1)
	end
end

--START/END A RAID
function flsys:StartRaid(raidname)
	local mlid = select(3, GetLootMethod())
	if db.inprogress then
		flsys:Print("You already have a raid in progress.")
	elseif not IsInRaid() then
		flsys:Print("You are not in a raid.")
	elseif not mlid then
		flsys:Print("You must be the masterlooter to start a raid.")
	else 		
		local mlname = select(1, GetRaidRosterInfo(mlid))
		if mlname~=GetUnitName("player") then
			self:Print("You must be the masterlooter to start a raid.")
		else
			self:RegisterEvent("GROUP_ROSTER_UPDATE")
			fld:Enable()
			db.inprogress = raidname or "Raid"
			flsys:MainButtons()
			db.dates[1] = date("%m/%d/%y")
			flsys:CreateRoster()
			flsys:AddtoEPGPLog(0, "start", "all", db.inprogress.." started", 0)  --FIX
			fld:StartRaid()
			flsys:SendVersion()
			if db.mode==1 then
				if db.promptrecur then
					StaticPopup_Show("START_RECUR")
				end
				if db.autoexpense then
					self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
					self:RegisterEvent("TRADE_ACCEPT_UPDATE")
				end
			elseif db.mode==2.1 then
				flsys:MassEP(4000, "single, GP")
			elseif db.mode==2.2 then
				flsys:MassEP(3, "single, count")
			end	
		end		
	end
end

function flsys:ResumeRaid()
	flsys:UpdateRaid()
	if db.next_award>0 then
		flsys:Print("Recurring EP award resumed.")
		fra:Show()
	end
	flsys:RegisterEvent("GROUP_ROSTER_UPDATE")
	if flsys.db.profile.autoexpense then
		flsys:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		flsys:RegisterEvent("TRADE_ACCEPT_UPDATE")
	end
	fld:Enable()
	fld:StartRaid()
end

function flsys:EndRaid()
	if db.inprogress then
		flsys:AddtoEPGPLog(0, "end", "all", "Raid ended") --FIX customize which raid
		db.inprogress=false
		self:Print("Raid ended.")
		for i = raidstocount, 2, -1 do
			db.dates[i] = db.dates[i-1]
		end
		db.dates[1]=""
		for name, ntable in pairs(db.players) do
			if db.players[name].temp or db.players[name].alt then
				flsys:debug(3, "Removing", name, "from system (alt or sub)")
				flsys:RemovePlayer(name)
			else
				db.players[name].inraid=nil
			end
		end
		flsys:EndRecur()
		self:UnregisterEvent("GROUP_ROSTER_UPDATE")
		self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		self:UnregisterEvent("TRADE_ACCEPT_UPDATE")
		fld:Disable()
		flsys:RefreshSortList()
		if db.mode==1 then StaticPopup_Show("DECAY") end
	else
		self:Print("You do not have a raid in progress.")
	end
end

function flsys:DecayRaid()
	for name,_ in pairs(db.players) do
		db.players[name].ep_total = 0
		db.players[name].gp_total = 0
		local start = #db.players[name].ep_data
		if start<raidstocount then
			start = start+1
		end
		for i=start, 2, -1 do
			db.players[name].ep_data[i] = math.floor((db.players[name].ep_data[i-1] or 0)*(raidstocount-i+1)/(raidstocount-i+2))
			db.players[name].gp_data[i] = math.floor((db.players[name].gp_data[i-1] or 0)*(raidstocount-i+1)/(raidstocount-i+2))
			db.players[name].ep_total = db.players[name].ep_total+db.players[name].ep_data[i]
			db.players[name].gp_total = db.players[name].gp_total+db.players[name].gp_data[i]
		end
		db.players[name].ep_data[1] = 0
		db.players[name].gp_data[1] = 0
		if db.players[name].position then 
			db.players[name].position = db.players[name].position-1
			if db.players[name].position==1 then 
				db.players[name].position = nil
			end
		end
	end
	flsys:Print("EP and GP decayed.")
	flsys:AddtoEPGPLog(0, "decay", "all", "Decayed EP and GP")
	flsys:UpdatePR()
end

--RAID ROSTER
function flsys:CreateRoster()
	local notinsys = {}
	numraidmembers = GetNumGroupMembers()
	flsys:debug(3, "Creating roster, "..numraidmembers.." members")
	for i=1, numraidmembers do
		local name = select(1, GetRaidRosterInfo(i))
		if db.players[name] then
			db.players[name].inraid = true
		elseif db.alts_data[name] and db.players[db.alts_data[name]] then
			flsys:NewPlayer(name, true, false, true)
		else
			flsys:NewPlayer(name, true, true)
		end	
	end
	flsys:RefreshSortList()
end

function flsys:GROUP_ROSTER_UPDATE()
	if not IsInRaid() then
		flsys:debug(3, "GROUP_ROSTER_UPDATE - player no longer in raid")
		StaticPopup_Show("ENDRAID")
	elseif GetNumGroupMembers() ~=numraidmembers then
		flsys:debug(3, "GROUP_ROSTER_UPDATE - # raid members changed")
		flsys:UpdateRaid()
		fld:CreateRoster()		
	end
end

function flsys:UpdateRaid()
	for name, ntable in pairs(db.players) do
		db.players[name].inraid=nil
	end
	flsys:CreateRoster()
end

--MAIN FRAME DISPLAY
function flsys:ToggleMainFrame()
	if maindisplay==1 then
		maindisplay=2
	else
		maindisplay=1
	end
	FLPlayerFrame:Hide()
	FLSysAward:Hide()
	flsys:MainButtons()
end

function flsys:MainButtons() --portrait, buttons at bottom
	if maindisplay==1 then
		Heading:Show()
		SetPortraitToTexture(FLMainPortrait, "Interface\\Icons\\Achievement_Arena_5v5_6")
		FLMainTitleText:SetText("         Standings")
		FLMainButton2:Show()
		if not db.inprogress then
			FLMainButton1:SetText("Start")
			FLMainButton1:SetScript("OnClick", function() StaticPopup_Show("STARTRAID") end)
			FLMainButton2:SetText("Export")
			FLMainButton2:SetScript("OnClick", function() flsys:ShowExportFrame("standings") end)
		else
			FLMainButton1:SetText("End")
			FLMainButton1:SetScript("OnClick", function() StaticPopup_Show("ENDRAID") end)
			FLMainButton2:SetText("Mass EP")
			FLMainButton2:SetScript("OnClick", function() flsys:ShowSysAward() end)
		end
		FLLogExport:SetScript("OnClick", function() flsys:ShowExportFrame("gear") end)
	else
		Heading:Hide()
		SetPortraitToTexture(FLMainPortrait, "Interface\\Icons\\Ability_Racial_PackHobgoblin")
		FLMainTitleText:SetText("    Raid Expenses")
		FLMainButton2:Hide()
		FLMainButton1:SetText("Add")
		FLMainButton1:SetScript("OnClick", function() 
			FLPlayerFrameName:SetText("Expense")
			FLPlayerFrame:Show()
			end)
		FLLogExport:SetScript("OnClick", function() flsys:ShowExportFrame("cost") end)
	end
	flsys:UpdateMain()
end

function flsys:UpdateMain() --updates the player buttons - script & text
	flsys:debug(3, "Updating main display lists")
	if maindisplay==1 then
		for i, name in ipairs(db.sortlist) do
			local b = rowbuttons[i]
			b:SetScript("OnMouseUp", function(self, button) 
					if button=="LeftButton" then
						flsys:ShowSysAward(name) 
					elseif button=="RightButton" then
						flsys:SendStandings(name)
					end
				end)
			if db.players[name].inraid then
				b.cells[1]:SetText("|cffCCFFFF"..name)
				b.cells[2]:SetText("|cffCCFFFF"..db.players[name].ep_total)
				b.cells[3]:SetText("|cffCCFFFF"..db.players[name].gp_total)
				b.cells[4]:SetText("|cffCCFFFF"..db.players[name].current_pr)
				if db.players[name].temp then
					b.cells[2]:SetText("|cffCCFFFF-")
					b.cells[4]:SetText("|cffCCFFFF-")
				end
			else
				b.cells[1]:SetText(name)
				b.cells[2]:SetText(db.players[name].ep_total)
				b.cells[3]:SetText(db.players[name].gp_total)
				b.cells[4]:SetText(db.players[name].current_pr)
			end
		end
	else
		for i, name in ipairs(db.sortlist) do
			local b = rowbuttons[i]
			b.cells[1]:SetText(name)
			b.cells[2]:SetText("")
			b.cells[4]:SetText("")
			if name==GetUnitName("player") then
				b:SetScript("OnMouseUp", function(self, button) end)
				b.cells[3]:SetText("|cffCCFFFF--")
			else
				b:SetScript("OnMouseUp", function(self, button) 
					if button=="LeftButton" then
						FLPlayerFrameName:SetText("Payment - "..name)
						FLPlayerFrame:Show()
					elseif button=="RightButton" then
						flsys:SendBalance(name)
					end
				end)
				if db.players[name].balance<0 then
					b.cells[3]:SetText("|cffCCFFFF"..-db.players[name].balance)
				else
					b.cells[3]:SetText("|cffff9933"..db.players[name].balance)
				end
			end
		end
	end
	flsys:RosterPage(0)
end

function flsys:CheckRows()--creates & places row per sortlist if there isn't one already
	flsys:debug(3, "Checking rows")
	for i=1, #db.sortlist do
		if not rowbuttons[i] then
			local row = flsys:CreateTableRow({"-", "-", "-", "-"}, widths, FLMain)
			if i%13 ~= 0 then
				row:SetPoint("TOPLEFT", FLMain, "TOPLEFT", 18, -53-15*(i%13))
			else
				row:SetPoint("TOPLEFT", FLMain, "TOPLEFT", 18, -53-15*13)
			end
			rowbuttons[i] = row
		end
	end
end

function flsys:CreateTableRow(texttable)
	local widths = {77,42,42,42}
	local row = CreateFrame("Button", nil, FLMain)
	row:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight", "ADD")
	row:SetSize(200,14)
	row:RegisterForClicks("AnyUp", "AnyDown")
	row.cells = {}
	for i,w in ipairs(widths) do
		local c = row:CreateFontString(nil, "ARTWORK", "ChatFontSmall")
		c:SetJustifyH("LEFT")
		c:SetWidth(w)
		if #row.cells == 0 then
			c:SetPoint("LEFT", row, "LEFT", 0, 0)
		else
			c:SetPoint("LEFT", row.cells[#row.cells], "RIGHT", 0, 0)
		end
		c:SetText(texttable[i])
		table.insert(row.cells, c)
	end
	return row
end

function flsys:RosterPage(pg)
	rosterpage = rosterpage + pg
	for i, button in ipairs(rowbuttons) do
		if i<=#db.sortlist and i>rosterpage*13 and i<=(rosterpage+1)*13 then
			button:Show()
		else
			button:Hide()
		end
	end
	if rosterpage==0 then
		FLMainPrev:Hide()
	else
		FLMainPrev:Show()
	end
	if (rosterpage+1)*13>=#db.sortlist then
		FLMainNext:Hide()
	else
		FLMainNext:Show()
	end
end

--SIDE FRAMES
function flsys:ShowSysAward(name)
	FLSysAwardreason:SetFocus() 
	FLSysAwardreason:SetText("") 
	FLSysAwardamt:SetText("")
	if not name then
		FLSysAward:SetHeight(100)
		FLSysAwardreason:SetPoint("TOPLEFT", 10, -35)
		FLSysAwardFade:Hide()
		FLSysAwardLine:Hide()
		PanelTemplates_SetTab(FLSysAward, 3)
		FLSysAwardTab1:Hide()
		FLSysAwardTab2:Hide()
		FLSysAward.TitleText:SetText("Mass EP")
		FLSysAwardEnter:SetText("EP")
		FLSysAwardLowerButton:Show()
		if db.next_award>0 then
			FLSysAwardText:SetText("Next award in "..flsys:Round((db.next_award-GetTime())/60).." min")
			FLSysAwardText:Show()
			FLSysAwardLowerButton:SetText("End recurring award")
			FLSysAwardLowerButton:SetScript("OnClick", function() flsys:CheckEndRecur() end)
		else
			FLSysAwardText:Hide()
			FLSysAwardLowerButton:SetText("Start recurring award")
			FLSysAwardLowerButton:SetScript("OnClick", function() flsys:AsktoSetupRecur() end)
		end
	else
		FLSysAwardreason:SetPoint("TOPLEFT", 10, -55)
		FLSysAwardFade:Show()
		FLSysAwardLine:Show()
		FLSysAwardText:Hide()
		FLSysAward:SetHeight(87)
		FLSysAward.TitleText:SetText(name)
		FLSysAwardTab1:Show()
		FLSysAwardTab2:Show()
		FLSysAwardLowerButton:Hide()
	end
	FLSysAward:Show()
end

function flsys:SysAwardTabbed(num)
	if num==1 then
		FLSysAwardEnter:SetText("GP")
	elseif num==2 then
		FLSysAwardEnter:SetText("EP")
	end
end

--GP
function flsys:OnLootAwarded(name, link, id, amount)
	flsys:debug(3, "on loot awarded called: "..name..link..amount)
	if db.players[name] then
		flsys:AddGP(name, amount, link, id)
	end
end

function flsys:GetValue(level, itemid, equipLoc) --from LibGearPoints-1.2 (EPGP), changed slightly
	if db.mode~=2.2 then
		itemid=tonumber(itemid)
		if CUSTOM_ITEM_DATA[itemid] then
			level, equipLoc = unpack(CUSTOM_ITEM_DATA[itemid])
		end

		local slot_multiplier1 = EQUIPSLOT_MULTIPLIER_1[equipLoc]
		local slot_multiplier2 = EQUIPSLOT_MULTIPLIER_2[equipLoc]
		if not slot_multiplier1 then
			return 0
		end

		local gp_base = 1000*2^((level-standard_ilvl)/26)
		local high = math.floor(0.5 + gp_base * slot_multiplier1)
		local low = slot_multiplier2 and math.floor(0.5 + gp_base * slot_multiplier2) or nil
		flsys:debug(3, "Returning "..high.." GP value")
		return high, low
	else
		return 1
	end
end

function flsys:AddGP(name, amount, itemname, id)
	flsys:debug(2, "Adding GP: "..name..amount..itemname)
	db.players[name].gp_data[1] = db.players[name].gp_data[1]+ amount
	db.players[name].gp_total = db.players[name].gp_total + amount
	flsys:AddtoEPGPLog(amount, "GP", name, itemname, id)
	flsys:UpdatePR()
end

function flsys:ScaleGP(oldstd, newstd)
	local div = 2^((newstd-oldstd)/26)
	for name, nt in pairs(db.players) do
		nt.gp_total = flsys:Round(nt.gp_total/div)
		for i, g in ipairs(nt.gp_data) do
			nt.gp_data[i] = flsys:Round(g/div)
		end
	end
	flsys:AddtoEPGPLog(0, "decay", "all", "GP scaled: "..oldstd.." to "..newstd, 0)
	flsys:UpdatePR()
end

function flsys:ResetGP()
	for name, nt in pairs(db.players) do
		nt.gp_total=0
		for i, g in ipairs(nt.gp_data) do
			nt.gp_data[i] = 0
		end
	end
	flsys:AddtoEPGPLog(0, "RESET", "all", "Reset all GP")
	flsys:UpdatePR()
	self:Print("Reset all GP.")
end

--EP
function flsys:AddEP(name, amount, reason, mass)
	flsys:debug(2, "Adding EP: "..name..amount..reason)
	local posi = db.players[name].position or 1
	amount = math.floor(amount*(raidstocount+1-posi)/raidstocount)
	if db.players[name].alt then 
		name = db.alts_data[name] 
	end
	db.players[name].ep_data[posi] = db.players[name].ep_data[posi]+ amount
	db.players[name].ep_total = db.players[name].ep_total + amount
	if not mass then
		flsys:AddtoEPGPLog(amount, "EP", name, reason, posi)
		flsys:UpdatePR()
	end
end

function flsys:MassEP(amount, reason)
	if db.inprogress then
		local namelist=""
		for name,_ in pairs(db.players) do
			if db.players[name].inraid then
				flsys:AddEP(name, amount, reason, true)
				namelist = namelist..name..", "
			end
		end
		flsys:AddtoEPGPLog(amount, "EP", string.sub(namelist, 1, -3), reason)
		flsys:UpdatePR()
		if db.mode==1 then
			flsys:Print(amount.."EP awarded to raid.")
		end
	else
		flsys:Print("There is no active raid.")
	end
end

function flsys:StartRecur(minutes) --should do this check before the popup
	if db.next_award>0 then
		flsys:Print("You already have a recurring award in progress.  /fs endrecur to end it.")
	elseif minutes>=0 and minutes<60 and db.inprogress then
		local start = GetTime()+minutes*60
		db.next_award=start
		flsys:Print("Recurring award starts in "..minutes.."min. "..ep_amt.." EP will be awarded every "..ep_recur.." min.")
		flsys:debug(3, "Recurring award starts in "..minutes.."min. "..ep_amt.." EP will be awarded every "..ep_recur.." min.")
		fra:Show()
	elseif not db.sortlist[1] then
		flsys:Print("Recurring awards can only take place during an active raid.  /fs startraid to begin one.")
	else
		flsys:Print("Invalid entry.  Type /fs startrecur to bring up the window again.  Enter a number between 0 and 60.")
	end
end

function flsys:EndRecur()
	db.next_award=0
	flsys:debug(3, "Ending recurring")
	fra:Hide()
end

local interval = 0
local currtime
function flsys:CheckTime(self, elapsed) --adapted from the frame/func in epgp_recurring
	currtime = GetTime()
	interval = interval + elapsed
	if interval>30 then
		interval = 0
		if currtime > db.next_award then
			flsys:MassEP(ep_amt, db.inprogress)
			db.next_award = db.next_award + ep_recur*60
		end
	end
end

--PR & SORTING
function flsys:UpdatePR() --BY: StartRaid, EndRaid, AddEP, AddGP, MassEP, RefreshSortList | DOES: gets each players PR, sorts sortlist, sends standings | CALLS: UpdateMain
	flsys:debug(2, "SORT", "Updating PR, sorting")
	for name, i in pairs(db.players) do
		i.current_pr = flsys:GetPR(name)
	end
	table.sort(db.sortlist, function(name1, name2)
			return flsys:SortWrapper(name1, name2)
		end)
	if db.inprogress then
		flsys:SendStandings("raid")
	end
	flsys:MainButtons()
end

function flsys:GetPR(name)
	local pr
	if not ((db.mode==1 and db.players[name].temp) or db.players[name].alt) then
		if db.mode==2.2 then min_gp=.5 end
		local gp = math.max(db.players[name].gp_total, min_gp)
		local ep = db.players[name].ep_total
		pr = flsys:Round(ep/gp, 2)
	else
		pr = 0
	end
	return pr
end

function flsys:SortWrapper(name1, name2)
	if db.players[name1].inraid~=db.players[name2].inraid then
		return db.players[name1].inraid
	elseif db.players[name1].temp~=db.players[name2].temp then
		return db.players[name2].temp
	else
		return flsys:SortByPR(name1, name2)
	end
end

function flsys:SortByPR(name1, name2)
	if db.players[name1].current_pr ~= db.players[name2].current_pr then
		return db.players[name1].current_pr > db.players[name2].current_pr
	else
		return db.players[name1].gp_total < db.players[name2].gp_total
	end
end

--DATABASE OF PLAYERS
function flsys:ModeChanged(mode)
	if mode==1 then
		if not db.players[GetUnitName("player")] then
			flsys:NewPlayer(GetUnitName("player"))
		end
	else
		flsys:ResetData(true)
	end
end

function flsys:AddPlayerEntered(done) --CALLS: CheckRows, RefreshSortList
	local name = flsys:Cap(FLAddPlayerPlayer:GetText())
	local ep = FLAddPlayerEP:GetNumber()
	local gp = FLAddPlayerGP:GetNumber()
	local new = FLAddPlayerCheck:GetChecked()
	if name=="" then
		self:Print("Please enter a player name.")
	elseif db.players[name] and not db.players[name].temp then
		self:Print(name.." is already in the system.  If you want to reset their data, remove them and then add.")
	else
		flsys:debug(3, "Adding player: "..name..", EP: "..ep..", GP: "..gp)
		flsys:NewPlayer(name, nil, nil, nil, new, ep, gp)
		flsys:ClearImport()
		if done then
			FLAddPlayer:Hide()
			flsys:InitializeFrames()
		end			
	end
end

function flsys:ClearImport() --resets the import input areas
	FLAddPlayerPlayer:SetText("")
	FLAddPlayerEP:SetNumber(0)
	FLAddPlayerGP:SetNumber(0)
	FLAddPlayerCheck:SetChecked(false)
end

function flsys:NewPlayer(name, inraid, temp, alt, new, ep, gp)
	db.players[name] = { --applies to all
		inraid = inraid,
		temp = temp or false,
		alt = alt,
		balance = 0,
		ep_data = {[1] = 0},
		gp_data = {[1] = 0},	
	}
	if new then
		db.players[name].position = db.newplayerst
	end
	if ep and gp then
		db.players[name].ep_total = flsys:Round(ep*(raidstocount-1)/(raidstocount))
		db.players[name].gp_total = flsys:Round(gp*(raidstocount-1)/(raidstocount))
		db.players[name].gp_data[2] = db.players[name].gp_total
		db.players[name].ep_data[2] = db.players[name].ep_total			
	else
		db.players[name].ep_total = 0
		db.players[name].gp_total = 0
	end
	if db.inprogress then
		flsys:UpdateRaid()
	end
	flsys:RefreshSortList()
end

function flsys:AddAlt(info, input)
	local aremove, alt, main = string.match(input, "(-*)([^%d%s%p]+)=*([^%d%s%p]*)")
	if alt then alt = flsys:Cap(alt) end
	if main then main = flsys:Cap(main) end
	if aremove and db.alts_data[alt] then
		db.alts_data[alt] = nil
		flsys:Print(alt.." removed from alts list.")
	elseif alt and main then
		if not db.players[main] then
			self:Print(main.." is not in the database.  Add them before adding their alts.")
		else
			db.alts_data[alt] = main
			flsys:Print(alt.." added to alts list.")
		end
	else
		flsys:Print("Invalid entry. Make sure to format 'altname=mainname' without spaces")
	end
	alts_data = db.alts_data
end

function flsys:RemovePlayer(name)
	FLRosterFrame:Hide()
	if db.inprogress then
		self:Print("Cannot remove players during a raid.")
	else
		flsys:debug(3, "Removing "..name.." from system.")
		db.players[name]=nil
		if db.mode==1 then self:Print(name.." removed from database.") end
		flsys:RefreshSortList()
	end
end

function flsys:Import()
	InterfaceOptionsFrame:Hide()
	FLImportDataData:SetText("")
	FLImportData:Show()
end

function flsys:ImportEntered(imptext, fromplayer)
	if db.inprogress then
		self:Print("You cannot import or receive data while you have a raid in progress.")
		return
	end
	if imptext and imptext~="" then
		local printmsg, sendplayer, sendplayererror
		for psection in string.gmatch(imptext, "@([^@]+)") do
			local player = string.match(psection, "^([^=]+)")
			local eppos = string.find (psection, "ep:")
			local balpos = string.find (psection, "bal:") or -1
			if not player or not eppos or not string.find(psection, "gp:") then
				printmsg = "Import text not formatted correctly. Make sure you paste the entire text exactly as it is in the spreadsheet.  If you're seeing this error after receiving data from another player, please go to curse.com/addons/wow/flaming-ml and report a bug."
				sendplayererror = "could not import your data correctly.  This is probably an addon bug.  Please go to curse.com/addons/wow/flaming-ml and report it."
			else
				FLImportData:Hide()
				flsys:NewPlayer(player)
				local currpart = string.sub(psection, 1, eppos)
				local pos = 1
				for amt in string.gmatch(currpart, "(%d+)") do --filling in gp data, updating total
					amt = tonumber(amt)
					db.players[player].gp_data[pos] = amt
					db.players[player].gp_total = db.players[player].gp_total +amt
					pos = pos+1
				end
				currpart = string.sub(psection, eppos, balpos)
				pos = 1
				for amt in string.gmatch(currpart, "(%d+)") do --filling in epdata, updating total
					amt = tonumber(amt)
					db.players[player].ep_data[pos] = amt
					db.players[player].ep_total = db.players[player].ep_total +amt
					pos = pos+1
				end
				local bal = string.match(psection, "bal:(%-?%d+)")
				if bal then
					db.players[player].balance = tonumber(bal)
				end
				bal = string.match(psection, "new:(%d+)")
				if bal then
					db.players[player].position = tonumber(bal)
				end
				flsys:AddtoEPGPLog(0, "import", player, "Imported data for "..player)
				self:Print("Imported data for "..player..".")
				flsys:UpdatePR()
				sendplayer="has imported your data!"
			end
		end
		self:Print(printmsg)
		if fromplayer then
			if sendplayererror then
				SendAddonMessage("flamingsys", "datareply:"..sendplayererror, "WHISPER", fromplayer)
			elseif sendplayer then
				SendAddonMessage("flamingsys", "datareply:"..sendplayer, "WHISPER", fromplayer)
			end
		end
	else
		self:Print("You entered a blank import.  Copy the text from your data backup spreadsheet.  If you're seeing this error after trying to receive data from another player, confirm that they have data stored - if so, please go to curse.com/addons/wow/flaming-ml and report a bug.")
		if fromplayer then
			SendAddonMessage("flamingsys", "datareply: did not receive your data - either you have no data stored or there was an addon bug.  Please go to curse.com/addons/wow/flaming-ml and report it.", "WHISPER", fromplayer)
		end
	end
end

function flsys:ResetData(removeplayers)
	if removeplayers then
		wipe(db.players)
		self:Print("Removed all players and their data from the system.")
		flsys:AddtoEPGPLog(0, "RESET", "all", "Reset & removed all players")
		flsys:ClearLog()
	else
		for name, ntable in pairs(db.players) do
			flsys:NewPlayer(name)
		end
		self:Print("Reset data for all players.")
		flsys:AddtoEPGPLog(0, "RESET", "all", "Reset all EP and GP")
	end
	wipe(db.dates)
	flsys:RefreshSortList()
end

function flsys:RefreshSortList() --Wipes & recreates sortlist containing all players |CALLS: CheckRows(), UpdatePR()
	wipe(db.sortlist)
	for name,t in pairs(db.players) do
		if t then table.insert(db.sortlist, name) end
	end
	flsys:CheckRows()
	flsys:UpdatePR()
end

--SEND TO RAIDERS
function flsys:SendStandings(sender, uptodate)
	if uptodate then
		SendAddonMessage("flamingloot", "uptodate:", "WHISPER", sender)
	else
		sstr =""
		for i, name in pairs(db.sortlist) do
			sstr = sstr..name..": "
			if db.mode~=2.2 then
				sstr = sstr..db.players[name].current_pr.."\n"
			else
				sstr = sstr..db.players[name].gp_total.."\n"
			end
		end
		if sender=="raid" then
			SendAddonMessage("flamingloot", "standings:"..sstr, "RAID")
			db.lastbroadcast = time()
		else
			SendAddonMessage("flamingloot", "standings:"..sstr, "WHISPER", sender)
		end
	end
end

function flsys:SendBalance(player)
	SendAddonMessage("flamingloot", "balance:"..db.players[player].balance, "WHISPER", player)
end

function flsys:SendVersion()
	local vers = GetAddOnMetadata("flamingloot", "Version")
	local one, two, three = string.match(vers, "(%d).*(%d).*(%d)")
	if one and two and three then
		SendAddonMessage("flamingloot", "version:"..one..two..three, "RAID")
	end
end

function flsys:CHAT_MSG_ADDON(event, prefix, message, channel, sender)
	if prefix=="flamingsys" then
		local command, value = string.match(message, "(%a+):*(.*)")
		if command=="datareply" then
			self:Print(sender.." "..value)
		elseif command=="standings" then
			flsys:SendStandings(sender, (tonumber(value))<db.lastbroadcast)
		end
	end
end

function flsys:OnCommReceived(prefix, message, channel, sender)
	if prefix=="flamingsysdata" then
		local command, value = string.match(message, "(%a+):*(.*)")
		if command=="data" then
			local dialog = StaticPopup_Show("RECEIVE_DATA", sender)
			if dialog then
				dialog.text = value
				dialog.player = sender
			end
		end
	end
end

--SEND DATA
function flsys:SendData(name)
	self:SendCommMessage("flamingsysdata", "data:"..flsys:GetImportText(), "WHISPER", name)
	self:Print("Sending data to "..name..".  If they accept or decline the data you'll see a printout.  No further message means they don't have the addon turned on or they're using an outdated version.")
end

--LOG & EXPORT LOG
function flsys:Undo()
	if not db.epgplog[1] then
		self:Print("There is nothing to undo.")
	elseif  db.epgplog[1][3] == "EP" or db.epgplog[1][3] == "GP" then --going to undo
		local _, amount, logtype, player, _, _ = unpack(db.epgplog[1])
		if logtype == "GP" then
			if db.players[player] then
				db.players[player].gp_total = db.players[player].gp_total - amount
				db.players[player].gp_data[1] = db.players[player].gp_data[1] - amount
			end
			table.remove(db.epgplog, 1)
		elseif logtype == "EP" then
			for name in string.gmatch(player, "([^, ]+)") do
				db.players[name].ep_total = db.players[name].ep_total - amount
				db.players[name].ep_data[1] = db.players[name].ep_data[1] - amount
			end
			table.remove(db.epgplog, 1)
		end
		flsys:ShowLogFrame() 
		flsys:UpdatePR()
	else
		self:Print("Only GP and EP entries can be undone.") --won't be able to undo anything pre-decay because this will block it
	end
end

function flsys:AddtoEPGPLog(amount, logtype, player, reason, num)
	local timestamp = time()
	table.insert(db.epgplog, 1, {timestamp, amount, logtype, player, reason, num})
end

function flsys:LogItemtoString(logitem)
	local displaystring = ""
	local logdate, amount, logtype, players, reason, num = unpack(logitem)
	if logtype=="start" or logtype=="end" or logtype=="decay" or logtype=="import" or logtype=="RESET" then --TODO clean this up
		displaystring = displaystring..date("---- %m/%d/%y %H:%M", logdate).." "..reason.."----"
	else
		displaystring = displaystring..date("%m/%d %H:%M", logdate).." "
		if logtype=="EP" then
			if amount>0 then amount= "+"..amount end
			displaystring = displaystring..amount.." EP "..players.." ("..reason..")"
		elseif logtype=="GP" then
			displaystring = displaystring..reason.." "..players.." ("..amount.." GP)"
		end
	end
	return displaystring
end

function flsys:ClearLog(logtype)
	FLLog:Hide()
	if logtype=="epgp" then
		wipe(db.epgplog)
		flsys:Print("EPGP log cleared")
	elseif logtype=="cost" then
		wipe(db.costlog)
		flsys:Print("Cost log cleared")
	end
end

function flsys:ShowLogFrame() 
	local displaystring=""
	local count = 0
	if maindisplay==1 then
		for i, t in ipairs(db.epgplog) do
			if flsys:LogItemtoString(db.epgplog[i]) ~="" then
				displaystring = displaystring..flsys:LogItemtoString(db.epgplog[i]).."\n"
				count = count+1
			end
		end
		FLLogUndo:Show()
	else
		for i, t in ipairs(db.costlog) do
			displaystring = displaystring..flsys:CostLogtoString(i).."\n"
			count = count+1
		end
		FLLogUndo:Hide()
	end
	FLLogText:SetText(displaystring)
	FLLogContent:SetHeight(16*count)
	FLLog:Show()
end

function flsys:CostLogtoString(i)
	local coststr = date("%m/%d", db.costlog[i][1]).." "..(db.costlog[i][3])
	if db.costlog[i][4] =="expense" then
		if db.costlog[i][2]>0 then coststr=coststr.." +" end
	elseif db.costlog[i][4] =="payment" then
		coststr=coststr.." paid "
	end
	return coststr..(db.costlog[i][2]).."g"
end

function flsys:ShowExportFrame(exporttype)
	-- 1 timestamp 2 amount 3 type 4 player(s) 5 reason/item 6 itemid
	--spreadsheet order: 1 4 5 2 3 (6)
	local exporttext = ""
	if exporttype=="gear" then
		for i, entry in ipairs(db.epgplog) do
			exporttext = exporttext..date("%m/%d/%y %H:%M", entry[1]).."\t"..entry[4].."\t"..entry[5].."\t"..entry[2].."\t"..entry[3]
			if entry[6] then
				exporttext = exporttext.."\t"..entry[6]
			end
			exporttext = exporttext.."\n"
		end
		FLExportDone:SetScript("OnClick", function() FLExport:Hide(); flsys:ConfirmExportTime("epgp") end)
	elseif exporttype=="standings" then
		local ddate = date("%m/%d/%y %H:%M", time())
		for i, name in ipairs(db.sortlist) do
			exporttext = exporttext..name.."\t"..db.players[name].ep_total.."\t"..db.players[name].gp_total.."\t"..db.players[name].current_pr.."\t"..ddate
			if i==1 then
				exporttext = exporttext.."\t"..flsys:GetImportText()
			end
			exporttext = exporttext.."\n"
		end
		FLExportDone:SetScript("OnClick", function() FLExport:Hide(); end)
	elseif exporttype=="cost" then
		for i, logitem in ipairs(db.costlog) do
			exporttext = exporttext..date("%m/%d/%y %H:%M", logitem[1]).."\t"..logitem[2].."\t"..logitem[3].."\t"..logitem[4].."\n"
		end
		FLExportDone:SetScript("OnClick", function() FLExport:Hide(); flsys:ConfirmExportTime("cost") end)
	end
	if exporttext~="" then
		FLExportText:SetText(exporttext)
		FLExport:Show()
	else
		self:Print("Nothing to export.")
	end
end

function flsys:GetImportText() --not during combat?
	local importstr =""
	for name, nt in pairs(db.players) do
		importstr = importstr.."@"..name.."=gp:"
		for i, amt in ipairs(db.players[name].gp_data) do
			importstr = importstr..amt..","	
		end
		importstr = importstr.."ep:"
		for i, amt in ipairs(db.players[name].ep_data) do
			importstr = importstr..amt..","
		end
		if db.mode==1 then
			importstr = importstr.."bal:"..db.players[name].balance
			if db.players[name].position then
				importstr = importstr.."new:"..db.players[name].position
			end
		end
	end
	return importstr
end

function flsys:ConfirmExportTime(exporttype)
	dialog = StaticPopup_Show("EXPORT_COMPLETE", exporttype)
	if dialog then
		dialog.etype = exporttype
	end
end

--EXPENSES
function flsys:CostAmtEntered(title, amount)
	if title=="Expense" then
		if db.inprogress then
			flsys:Expense("Misc", amount)
		else
			flsys:Expense("Misc", amount, true)
		end
	else
		local player = string.match(title, "-%s([^%d%s%p]+)")
		flsys:PaymentRec(player, amount)
	end
end

function flsys:Expense(expensetype, amount, all)
	expensetype = expensetype or ""
	amount = amount or db.costs[expensetype] or 0
	db.costtotal = db.costtotal + amount
	local numplayers = numraidmembers
	if not db.inprogress then
		numplayers = #db.sortlist
	end
	table.insert(db.costlog, 1, {time(), amount, expensetype, "expense"})
	for name,v in pairs(db.players) do
		if (v.inraid and (not v.temp)) or all then
			if v.alt then name = db.alts_data[name] end
			db.players[name].balance = db.players[name].balance + flsys:Round(amount/numplayers)
			if db.inprogress and not v.alt then flsys:SendBalance(name) end
		end
	end
	self:Print("Added "..amount.."g to expenses")
	flsys:UpdateMain()
end

function flsys:COMBAT_LOG_EVENT_UNFILTERED(event, timestamp, subevent, hideCaster, srcGUID, srcname, srcflags, srcRaidFlags, dstGUID, dstname, dstflags, dstRaidFlags, spellID, spellname)
	if not subevent then
		return
	end
	if not UnitAffectingCombat("player") then
		local expense
		if spellID == 87644 and subevent == "SPELL_CREATE" then -- Seafood Magnifique Feast 3m
			expense="feast"
		elseif subevent=="SPELL_CAST_START" then
			if spellID == 92649 then -- Cauldron of Battle 10m
			expense="cauldron"
			elseif spellID == 92712 then -- Big Cauldron of Battle 10m
			expense="bigcauldron"
			end
		end
		if srcname and expense then
			flsys:Expense(expense)
			if srcname~=GetUnitName("player") then
				flsys:PaymentRec(srcname, db.costs[expense])
			end
		end
	end
end

function flsys:PaymentRec(player, amount)
	if player and amount then
		table.insert(db.costlog, 1, {time(), amount, player, "payment"})
		db.players[player].balance = db.players[player].balance - amount
		self:Print("Received payment of "..amount.."g from "..player.." - current balance of "..db.players[player].balance)
		if UnitInRaid(player) then
			SendAddonMessage("flamingloot", "payment:"..amount..";"..db.players[player].balance, "WHISPER", player)
		end
		db.costrec = db.costrec+amount
		flsys:UpdateMain()
	end
end

function flsys:TRADE_ACCEPT_UPDATE(event, ps, ts)
	flsys:debug(3, "EXPENSES", "trade update:", ps, ts)
	if ps==1 and ts==1 and GetTargetTradeMoney()>0 then
		local dialog = StaticPopup_Show("ENTERPAYMENT")
		if dialog then
			dialog.player = UnitName("npc")
			dialog.amount = GetTargetTradeMoney()/10000
		end
	end
end

function flsys:ResetExpenses()
	for k,v in pairs(db.players) do
		v.balance = 0
	end
	db.costtotal=0
	db.costrec=0
	self:Print("Reset expenses")
end

--POPUP CALLS
function flsys:AsktoSetupRecur()
	StaticPopup_Show("START_RECUR")
end

function flsys:CheckEndRecur()
	StaticPopup_Show("ENDRECUR")
end

function flsys:DecayPressed()
	StaticPopup_Show("DECAY")
end

function flsys:CheckAwardEnter()
	--to enable/disable entry buttons
	local reason = FLSysAwardreason:GetText()
	local amt = FLSysAwardamt:GetNumber()
	if reason~="" and amt~=0 then
		FLSysAwardEnter:Enable()
	else
		FLSysAwardEnter:Disable()
	end
end

function flsys:AwardEntered()
	local name = FLSysAward.TitleText:GetText()
	local reason = FLSysAwardreason:GetText()
	local amt = math.floor(FLSysAwardamt:GetNumber())
	if FLSysAward.selectedTab==1 then --GP
		flsys:AddGP(name, amt, reason)
	elseif FLSysAward.selectedTab==2 then --EP
		flsys:AddEP(name, amt, reason)
	elseif FLSysAward.selectedTab==3 then --MassEP
		flsys:MassEP(amt, reason)
	end
	FLSysAward:Hide()
end

function flsys:ResetDataPressed() --inprogress check done
	StaticPopup_Show("DATARESET")
end

function flsys:ResetLogPressed()
	StaticPopup_Show("LOGRESET")
end

function flsys:EndPressed()
	StaticPopup_Show("ENDRAID")
end

function flsys:RemovePlayerPressed(player)
	if player then
		local dialog = StaticPopup_Show("REMOVEPLAYER", player)
		if dialog then
			dialog.player = player
			dialog.enterClicksFirstButton = true
		end
	end
end

function flsys:ResetGPPressed()
	StaticPopup_Show("RESET_GP")
end

--POPUP DIALOGS
StaticPopupDialogs["DATARESET"] = {
	text = "Also remove all players from the database?",
	button1 = "Yes",
	button2 = "No",
	button3 = "Cancel",
	timeout = 0,
	hideOnEscape = 1,	
	whileDead = 1,                  
	OnAccept = function(self) flsys:ResetData(true) end,
	OnCancel = function(self) flsys:ResetData(false) end,
}

StaticPopupDialogs["LOGRESET"] = {
	text = "Delete all log info?",
	button1 = ACCEPT,
	button2 = CANCEL,
	timeout = 0,
	hideOnEscape = 1,	
	whileDead = 1,                  
	OnAccept = function(self) flsys:ClearLog() end,
}

StaticPopupDialogs["RESET_GP"] = {
	text = "Reset all players' GP to 0?  This cannot be undone.",
	button1 = ACCEPT,
	button2 = CANCEL,
	timeout = 0,
	hideOnEscape = 1,	
	whileDead = 1,                  
	OnAccept = function(self) flsys:ResetGP() end,
}

StaticPopupDialogs["STARTRAID"] = {
	text = "Name of raid:",
	button1 = ACCEPT,
	button2 = CANCEL,
	timeout = 0,
	whileDead = 1,  
	hideOnEscape = 1,	
	hasEditBox = 1,
	maxLetters = 25,
	OnAccept = function(self)
		local text = self.editBox:GetText()
		flsys:StartRaid(flsys:Cap(text))
	end
}

StaticPopupDialogs["ENDRAID"] = {
	text = "End the raid?",
	button1 = ACCEPT,
	button2 = CANCEL,
	hideOnEscape = 1,	
	timeout = 0,
	whileDead = 1,	
	OnAccept = function(self) flsys:EndRaid() end,
	OnCancel = function()
		if not fld:IsEnabled() then
			flsys:ResumeRaid()
		end
	end,
}

StaticPopupDialogs["REMOVEPLAYER"] = {
	text = "Remove %s from the system? All of their data will be lost.",
	button1 = "Yes",
	hideOnEscape = 1,	
	button2 = "No",
	timeout = 0,
	whileDead = 1,                  
	OnAccept = function(self)
		flsys:RemovePlayer(self.player)
	end,
}

StaticPopupDialogs["START_RECUR"] = {
	text = "Number of minutes until first award should go out:",
	button1 = ACCEPT,
	button2 = CANCEL,
	timeout = 0,
	whileDead = 1, 
	enterClicksFirstButton = true,	
	hasEditBox = 1,
	maxLetters = 2,
	OnShow = function(self, data)
		self.editBox:SetText("0")
	end,
	OnAccept = function(self, data)
		FLSysAward:Hide()
		local minutes = tonumber(self.editBox:GetText())
		flsys:StartRecur(minutes)
	end
}

StaticPopupDialogs["ENDRECUR"] = {
	text = "End recurring EP award?",
	button1 = "Yes",
	button2 = "No",
	timeout = 0,
	enterClicksFirstButton = true,
	whileDead = 1,   
	hideOnEscape = 1,	               
	OnAccept = function(self) 
		FLSysAward:Hide()
		flsys:EndRecur() end,
}

StaticPopupDialogs["RESUME_RAID"] = {
	text = "Resume your raid?",
	button1 = "Yes",
	button2 = "No",
	timeout = 0,
	whileDead = 1,                  
	OnAccept = function(self) flsys:ResumeRaid() end,
	OnCancel = function(self) flsys:EndRaid() end,		
}

StaticPopupDialogs["NOTDURINGRAID"] = {
	text = "You cannot do that while a raid is in progress.",
	button1 = "Ok",
	timeout = 0,
	hideOnEscape = 1,	
	enterClicksFirstButton = true,
	whileDead = 1,                  	
}

StaticPopupDialogs["CONFIRM_RAIDSTOCOUNT"] = {
	text = "Change number of raids to count?",
	button1 = "Yes",
	button2 = CANCEL,
	timeout = 0,
	enterClicksFirstButton = true,
	hideOnEscape = 1,	
	whileDead = 1,                  
	OnAccept = function(self) 
		flsys.db.profile.raidstocount = self.input
		flsys.db.profile.newplayerst = math.floor(self.input/2)
		flsys:GetConstants()
		end,	
}

StaticPopupDialogs["EXPORT_COMPLETE"] = {
	text = "Did you successfully back up your data?  If so the %s log will be cleared.",
	button1 = "Yes",
	button2 = "No",
	timeout = 0,
	whileDead = 1,                  
    OnAccept = function(self)
        flsys:ClearLog(self.etype)
        end,
}

StaticPopupDialogs["DECAY"] = {
	text = "Decay ep and gp?",
	button1 = "Yes",
	button2 = "No",
	timeout = 0,
	hideOnEscape = 1,	
	enterClicksFirstButton = true,
	whileDead = 1,                  
	OnAccept = function()
		flsys:DecayRaid()
	end,
}

StaticPopupDialogs["ENTERPAYMENT"] = {
	text = "Enter payment?",
	button1 = "Yes",
	button2 = "No",
	hideOnEscape = 1,	
	timeout = 0,
	enterClicksFirstButton = true,
	whileDead = 1,                  
	OnAccept = function(self)
		flsys:PaymentRec(self.player, self.amount)
	end,
}

StaticPopupDialogs["SENDDATA"] = {
	text = "Send data to:",
	button1 = ACCEPT,
	button2 = CANCEL,
	timeout = 0,
	whileDead = 1,  
	hideOnEscape = 1,	
	hasEditBox = 1,
	maxLetters = 25,
	OnAccept = function(self)
		local name = self.editBox:GetText()
		flsys:SendData(name)
	end
}

StaticPopupDialogs["RECEIVE_DATA"] = {
	text = "%s is sending you loot standings. Accept them?\nWARNING: Imported data overwrites stored data!",
	button1 = "Yes",
	button2 = "No",
	timeout = 0,
	whileDead = 1,                  
	OnAccept = function(self)
		flsys:ImportEntered(self.text, self.player)
	end,
	OnCancel = function(self, reason)
		SendAddonMessage("flamingsys", "datareply:".."declined your data.", "WHISPER", self.player)
	end,
}

--MISC UTILITIES
function flsys:Round(num, dp)
  local mult = 10^(dp or 0)
  return math.floor(num * mult + 0.5) / mult
end

function flsys:TextTooltip(owner, text)
	GameTooltip:SetOwner(owner, "ANCHOR_RIGHT")
	GameTooltip:SetText(text)
	GameTooltip:Show()
end

function flsys:Print(text)
	if text then
		DEFAULT_CHAT_FRAME:AddMessage("|cff6600FFflsys:|r "..tostring(text))
	end
end

function flsys:Cap(str)
	local capstr = ""
	for word in string.gmatch (str, "[^%s]+") do
		if word~="of" and word~="the" and word~="and" and word~="a" and word~="or" then
			word = (word:gsub("^%l", string.upper))
		end
		capstr = capstr..word.." "
	end
	return string.sub(capstr, 1, -2)
end
